Feature: NumPy-compliant distributed advanced indexing - #938
Open
ClaudiaComito wants to merge 408 commits into
Open
ClaudiaComito wants to merge 408 commits into
ClaudiaComito wants to merge 408 commits into
Conversation
4 tasks
This was referenced Aug 30, 2022
4 tasks
ClaudiaComito
changed the base branch from
features/914_adv-indexing
to
main
February 10, 2023 17:49
This was referenced Aug 7, 2023
This was referenced Aug 21, 2023
Closed
Collaborator
|
just a comment: in the fft-module (if already merged at time merging this PR) some commented-out parts of |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #938 +/- ##
==========================================
+ Coverage 83.77% 84.27% +0.50%
==========================================
Files 105 105
Lines 15849 16488 +639
==========================================
+ Hits 13277 13895 +618
- Misses 2572 2593 +21
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
Contributor
|
This pull request is stale because it has been open for 60 days with no activity. |
Contributor
|
This pull request is stale because it has been open for 60 days with no activity. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Description
TL;DR
This PR replaces Heat's legacy, local-only indexing with 100% NumPy-API-compliant advanced indexing capabilities across distributed nodes.
You can now seamlessly use boolean masks, integer arrays, negative-step slices etc. on distributed arrays without manual data shuffling:
This pull request introduces a significant overhaul of distributed indexing within
dndarray.py, specifically targeting the__getitem__and__setitem__methods.The logic has been completely refactored to identify zero-communication paths ("early out") for standard slices, while routing heavy, unordered (non-sequential) advanced indexing through highly optimized MPI collective communication.
Also,Merged separately in #2332indexing.nonzero(), the kwargas_tuplehas been introduced (default:True) to comply with the Numpy API while giving users the choice to switch to torch-style output (2-D array).Main changes (LATEST UPDATE 18.9.2026)
dndarray.py_resolve_indexing_statehelper. This function torch-proofs allkeyinputs, handles broadcasting, aligns array dimension to indexed shape, and determines the indexing operation type for later dispatching. Returns a structuredProcessedKeyNamedTuple.__getitem__and__setitem__functions. They are now wrappers that call the resolution state and dispatch to dedicated methods (e.g.,__getitem_scalar,__setitem_mask,__getitem_advanced_local).MPI.Alltoallvfor cross-rank data fetching and assignment (__getitem_unorderedand__setitem_unordered)._resolve_duplicate_indicesto guarantee NumPy-compliant "last assignment wins" semantics when using advanced indexing with duplicate indices on GPUs (thanks @Hakdag97 ).__broadcast_valuehelper to automatically broadcast assigned values to match the target slice or boolean-mask shape during__setitem__operations.updateddiscarded as PyTorch named tensors are no longer supported__torch_proxy__to explicitly track thesplitaxis natively within the tensor's named dimensions for safer split axis tracking during dimensions-changing operations.__torch_proxy__to use PyTorchmetatensors, to perform lightweight shape and index validation without allocating tensor memoryintroduced INDEXING.md inthis will be addressed in a different PR.doc/source/and added it to the .rst indexindexing.pyChanges to the
indexingmodule have been merged with #2332.Summary of distribution semantics (UPDATED 16.9.2026)
array[key]array[key]splitand balanced status from the key.array[key]keyon split axis collapses that dimension, output is replicated on each process (split=None). For all other key types distribution is maintained.array[key]Communication path: Unordered distributed integer indices trigger
__getitem_unorderedwithAlltoallvexchange.array[key] = valarray[key] = valLocal arrays: Converted to a distributed array matching the target split axis and aligned via
redistribute_.array[key] = valvalue.split != target.split, raises aRuntimeError.array[key] = valarray[key] = valarray[key] = valUnordered integer indices:
keyis redistributed to matchvalue, followed by a dualAlltoallvshuffle (indices and data payload).Note: Extracting a single element along the split axis will collapse that dimension, resulting in
split=None.Internal getitem/setitem routing logic
UPDATE 16.9.2026
graph TD Start((Receive Key)) --> CheckDist{Is array distributed?} CheckDist -- No --> LocalFastPath[Unwrap key & index underlying tensor directly] CheckDist -- Yes --> CheckScalar{Is key a pure scalar<br/>and not boolean?} CheckScalar -- Yes --> EvalRoot{Compute root rank} EvalRoot --> OpScalar[op_type = 'scalar'] CheckScalar -- No --> CheckDistrMaskEarly{Is key a boolean mask<br/>aligned with array?} CheckDistrMaskEarly -- Yes --> OpDistrMask1[op_type = 'distr_mask'] CheckDistrMaskEarly -- No --> ResolveKeys[Resolve key & check bounds] ResolveKeys --> AssessOpType{_assess_op_type} AssessOpType -->|root is not None| OpScalar[op_type = 'scalar'] AssessOpType -->|split_key_is_ordered == 0| OpDist[op_type = 'distributed'] AssessOpType -->|split_key_is_ordered == -1| OpDesc[op_type = 'descending_slice'] AssessOpType -->|distr_mask_fast_path| OpDistrMask2[op_type = 'distr_mask'] AssessOpType -->|key_is_mask_like| OpLocalMask[op_type = 'local_mask'] AssessOpType -->|Default / Ordered / Slices| OpLocal[op_type = 'local'] %% Map to actual handlers subgraph Handlers [Target dispatch methods] OpScalar --> H_Scalar[__getitem_scalar<br/>__setitem_scalar] OpDist --> H_Dist[__getitem_advanced_distributed<br/>__setitem_advanced_distributed] OpDesc --> H_Desc[__getitem_descending_slice_distributed<br/>__setitem_descending_slice_distributed] OpDistrMask1 & OpDistrMask2 --> H_DistMask[__getitem_mask<br/>__setitem_mask] OpLocalMask & OpLocal --> H_Local[__getitem_local<br/>__setitem_local] end %% Styling classDef target fill:#d4edda,stroke:#28a745,stroke-width:2px; class H_Scalar,H_Dist,H_Desc,H_DistMask,H_Local target;Memory footprint
Scaling behaviour
Issue/s resolved: #703 #914 #918 #1012 #1019 #2135 #1816 #824
Type of change
Memory requirements
Performance
Will follow
Due Diligence
Does this change modify the behaviour of other functions? If so, which?
yes, everything that relied on the legacy indexing quirks (fixed) and everything that relied on 2D output from
nonzero()(also fixed)AI usage
We used frontier models (GPT, Gemini 3.1Pro - 3.8 extended), to help refactor, test, debug, optimize this PR, and to write the documentation.